package com.turtle3d;

import java.util.ArrayList;
import java.util.Date;

import javax.media.j3d.BranchGroup;

import com.turtle3d.formallanguage.TurtleController;
import com.turtle3d.formallanguage.grammar.Grammar;
import com.turtle3d.formallanguage.symbol.Symbol;
import com.turtle3d.formallanguage.symbol.SymbolFactory;
import com.turtle3d.gui.console.Console;
import com.turtle3d.gui.drawingpanel.DrawingPanel;
import com.turtle3d.gui.fractaloptions.GenerateFractalEvent;
import com.turtle3d.gui.fractaloptions.GenerateFractalListener;
import com.turtle3d.turtle.Turtle3D;
import com.turtle3d.turtle.Turtle3DImplementation;
import com.turtle3d.util.TaskTimer;

public class FractalGenerator implements GenerateFractalListener
{
	
	private DrawingPanel drawingPanel;
	private GenerateFractalEvent generateFractalEvent = null;
	private FractalGenerationThread fractalGenerationThread;

	public void generate(GenerateFractalEvent generateFractalEvent)
	{
		//if(!generateFractalEvent.isNextIteration() || this.generateFractalEvent==null)
			this.generateFractalEvent = generateFractalEvent;
		
		if(fractalGenerationThread!=null && fractalGenerationThread.isAlive()){
			App.printlnError("FractalGenerationThread is still alive! Wait...");
		}
		else{		
			fractalGenerationThread = new FractalGenerationThread();
			fractalGenerationThread.setPriority(Thread.MIN_PRIORITY);
			fractalGenerationThread.start();
		}
							
	}

	public DrawingPanel getDrawingPanel()
	{
		return drawingPanel;
	}

	public void setDrawingPanel(DrawingPanel printCanvas3D)
	{
		this.drawingPanel = printCanvas3D;
	}
	
	private ArrayList<Symbol> symbols;
	private int iteration;
	
	private class FractalGenerationThread extends Thread{								
		public void run(){
			try {
				Turtle3D t = new Turtle3DImplementation();

				TurtleController tm = new TurtleController(t);

				Grammar grammar = generateFractalEvent.getGrammar();

				TaskTimer.getTaskTimer().taskStart("symbolSequenceGeneration");
								
				if(!generateFractalEvent.isNextIteration()){
					iteration = generateFractalEvent.getIterations();
					SymbolFactory.getSymbolFactory().setDefaultParameter("iterationsCount",
							(float)iteration);
					
					symbols = grammar.generateSymbolSequence(generateFractalEvent.getIterations());
				}else{			
					if(symbols==null){
						iteration=1;
						SymbolFactory.getSymbolFactory().setDefaultParameter("iterationsCount",
								(float)iteration);
						symbols = grammar.generateSymbolSequence(iteration);
						
					}
					else{
						iteration++;
						
						SymbolFactory.getSymbolFactory().setDefaultParameter("iterationsCount",
								(float)iteration);
						symbols = grammar.nextIteration(symbols, iteration);
					}
				}
				
//				App.println(Grammar.printSymbolSequence(symbols, true, "+"));								

				long symbolCount = symbols.size();
				App.println(symbolCount+" symbols @ "+iteration+" iteration.");
				TaskTimer.getTaskTimer().taskComplete("symbolSequenceGeneration");
				TaskTimer.getTaskTimer().taskStart("turtleMovement");	

				tm.interpretLSymbols(symbols);		
				
				TaskTimer.getTaskTimer().taskComplete("turtleMovement");
				TaskTimer.getTaskTimer().taskStart("scenePreparation");

				
				BranchGroup branchGroup = (generateFractalEvent.getVisualizator()).visualize(tm
						.getVisualData());
				
				drawingPanel.setRecommendedFileName(grammar.getClass().getSimpleName()+"_"+generateFractalEvent.getVisualizator().getClass().getSimpleName()+"_"+iteration);
				drawingPanel.drawScene(branchGroup);
				
				//SymbolFactory.getSymbolFactory().initDefaultParameters();
					
				TaskTimer.getTaskTimer().taskComplete("scenePreparation");
						
				App.println("**SCENE READY**");
			} catch (Exception e) {
				App.printlnError("Scene generation aborted. Check console.");
				e.printStackTrace();
			}
		}
		
	}

}
